<template>
  <a-drawer :closable="true" :title="title" :visible="visible" :width="width" destroyOnClose placement="right" @close="close">
    <a-spin :spinning="confirmLoading">
      <!-- 主表单区域 -->
      <a-form-model
        ref="functionForm"
        :label-col="labelCol"
        :model="model"
        :wrapper-col="wrapperCol"
      >
        <a-form-model-item v-show="false" label="模型主键">
          <a-input v-model="model.modelId" readOnly></a-input>
        </a-form-model-item>
        <a-form-model-item ref="id" label="功能主键" prop="id">
          <a-input v-model="model.id" readOnly></a-input>
        </a-form-model-item>
        <a-form-model-item ref="code" :rules="rules.code" label="标识" prop="code">
          <a-input v-model="model.code" placeholder="请输入标识"></a-input>
        </a-form-model-item>
        <a-form-model-item ref="name" :rules="rules.name" label="名称" prop="name">
          <a-input v-model="model.name" placeholder="请输入名称"></a-input>
        </a-form-model-item>
        <a-form-model-item ref="type" :rules="rules.type" label="功能类型" prop="type">
          <a-select
            v-model="model.type"
            @getPopupContainer="(triggerNode) => triggerNode.parentNode"
          >
            <a-select-option v-for="type in functionTypeOptions" :key="type.value">{{ type.text }}</a-select-option>
          </a-select>
        </a-form-model-item>
        <a-form-model-item ref="isSync" :rules="rules.isSync" label="是否同步" prop="isSync">
          <a-switch v-model="model.isSync" :disabled="model.type !== 'found'" checkedChildren="同步" unCheckedChildren="异步" />
        </a-form-model-item>
        <a-form-model-item :labelCol="labelCol" :wrapperCol="{ span: '24' }">
          <a-card :hoverable="true" size="small" title="输入参数">
            <template slot="extra">
              <a-button icon="plus" @click="addRowParam"></a-button>
            </template>
            <a-row style="margin-bottom:10px" type="flex">
              <a-col :span="4">
                索引
              </a-col>
              <a-col :span="9">
                参数名称
                <a-tooltip>
                  <div slot="title">调用非只读数据节点</div>
                  <a-icon theme="twoTone" type="question-circle-o" />
                </a-tooltip>
              </a-col>
              <a-col :span="1"></a-col>
              <a-col :span="8">
                输入方式
                <a-tooltip>
                  <ui slot="title">
                    <li>多选下拉框：</li>
                    <li>实例注入：输入参数值在设备实例化是动态赋值，前端不能修改</li>
                    <li>前端操作：输入参数值在前端直接赋值</li>
                  </ui>
                  <a-icon theme="twoTone" type="question-circle-o" />
                </a-tooltip>
              </a-col>
              <a-col :span="2">操作</a-col>
            </a-row>
            <a-empty v-if="!model.inputParams" :description="false" />
            <a-row v-for="(param, index) in model.inputParams" :key="index" :gutter="10" style="margin:0px;" type="flex">
              <a-col :span="4">
                <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="">
                  <a-input-number v-model="param.sort" style="width:60px;"></a-input-number>
                </a-form-model-item>
              </a-col>
              <a-col :span="9">
                <a-form-model-item v-show="false" :labelCol="labelCol" :wrapperCol="wrapperCol" label="输入输出">
                  <a-input v-show="true" v-model="param.direction"></a-input>
                </a-form-model-item>
                <a-form-model-item ref="inputParams.id" :prop="'inputParams.'+index+'.id'" :rules="[{
                      required: true,
                      message: param.presetParam.name + (param.presetParam.description.length>0?('：' + param.presetParam.description):'')
                    }]">
                  <a-select
                    v-model="param.id"
                    :allowClear="true"
                    :placeholder="param.presetParam.name"
                    mode="default"
                    style="width: 100%"
                    @dropdownVisibleChange="(open) => inputParamsDropdownVisible(open, param.presetParam)"
                  >
                    <a-select-option v-for="option in inputParamsOptions" :key="option.id">{{option.name}}</a-select-option>
                  </a-select>
                </a-form-model-item>
              </a-col>
              <a-col :span="1">
                <a-tooltip>
                    <span slot="title">
                      {{ param['presetParam']['description'] }}
                    </span>
                  <a-icon theme="twoTone" type="question-circle-o" />
                </a-tooltip>
              </a-col>
              <a-col :span="8">
                <a-form-model-item ref="inputParams.inputMode" :prop="'inputParams.'+index+'.inputMode'" :rules="[{required: true, message: '请选择输入方式'}]">
                  <a-select
                    v-model="param.inputMode"
                    :allowClear="true"
                    placeholder="请选择输入方式"
                    style="width: 100%"
                  >
                    <a-select-option v-for="option in paramInputModeOptions" :key="option.value">
                      {{ option.text }}
                    </a-select-option>
                  </a-select>
                </a-form-model-item>
              </a-col>
              <a-col :span="2">
                <a-form-model-item>
                  <a-button :disabled="param.disDelete" icon="minus" @click="delRowParam(index)"></a-button>
                </a-form-model-item>
              </a-col>
            </a-row>
          </a-card>
        </a-form-model-item>
        <a-form-model-item v-show="model.isSync" :rules="[{ required: false, message: '请选择返回数据' }]" label="返回数据">
          <j-search-select-tag
            v-model="model.outputData"
            :dictOptions="outDataOptions"
            :triggerChange="true"
            placeholder="请输入用户性别"
            type="list"
          />
        </a-form-model-item>
        <a-form-model-item ref="" :rules="rules.description" label="描述" prop="description">
          <a-textarea v-model="model.description" allowClear placeholder="请输入描述" rows="3" />
        </a-form-model-item>
      </a-form-model>
    </a-spin>

    <div
      :style="{
        position: 'absolute',
        right: 0,
        bottom: 0,
        width: '100%',
        borderTop: '1px solid #e9e9e9',
        padding: '10px 16px',
        background: '#fff',
        textAlign: 'right',
        zIndex: 1
      }"
    >
      <a-button :style="{ marginRight: '10px' }" type="primary" @click="handleOk">确定</a-button>
      <a-button type="" @click="close">取消</a-button>
    </div>
  </a-drawer>
</template>

<script>
import pick from 'lodash.pick'
import JSearchSelectTag from '@/components/dict/JSearchSelectTag'
import JDictSelectTag from '@/components/dict/JDictSelectTag'
import { getAction, httpAction } from '@/api/manage'
import JMultiSelectTag from '@/components/dict/JMultiSelectTag'

export default {
  name: 'FuncDrawer',
  components: {
    JSearchSelectTag,
    JDictSelectTag,
    JMultiSelectTag
  },
  props: ['deviceModelId'],
  data() {
    return {
      form: this.$form.createForm(this),
      title: '',
      width: 500,
      visible: false,
      functionTypeOptions: [],
      executionWayOptions: [],
      paramInputModeOptions: [],
      baseModel: {
        code: '',
        modelId: '',
        id: '',
        isSync: false,
        name: '',
        type: '',
        executionWay: 'auto',
        inputParams: []
        // outputParam: {}
      },
      model: {},
      outDataOptions: [],
      inputParamsOptions: [],
      confirmLoading: false,
      labelCol: {
        span: 6
      },
      wrapperCol: {
        span: 16
      },
      rules: {
        code: [
          { required: true, message: '请输入标识!' },
          { min: 2, max: 20, message: '标识长度：2-20个字符' },
          {
            validator: (rule, value, callback) => this.validateDuplicateCode(this.model.modelId, this.model.id, value, callback)
          }
        ],
        name: [
          { required: true, message: '请输入名称!' },
          { min: 2, max: 20, message: '名称长度：2-20个字符' },
          { validator: (rule, value, callback) => this.validateDuplicateName(this.model.modelId, this.model.id, value, callback) }
        ],
        type: [{ required: true, message: '请选择功能类型!' }],
        executionWay: [{ required: true, message: '请选择功能执行方式!' }]
      },
      url: {
        add: '/device/model/addFunc',
        edit: '/device/model/editFunc',
        getTypes: '/device/model/getFunctionTypes',
        getExecutionWays: '/device/model/getExecutionWays',
        getInputModes: '/device/model/getInputModes',
        validateCode: '/device/model/validateFuncCode',
        validateName: '/device/model/validateFuncName'
      }
    }
  },
  created() {
    this.getOutDataOptions()
  },
  computed: {
    functionType() {
      return this.model.type
    }
  },
  watch: {
    functionType(val, oval) {
      console.log('watch-functionType', oval, '=>', val)
      if(oval){
        this.model.inputParams = []
      }

      this.functionTypeChanged(val)
    }
  },
  mounted() {
    this.getFunctionTypes()
    this.getExecutionWays()
    this.getParamInputMode()
  },
  methods: {
    functionTypeChanged(type) {
      let scope = this
      if (type !== 'found') {
        this.model.isSync = false
      }
      // 获取所有参数下拉选
      this.getInputParamsOptions('')
      /* 表单输入参数、功能参数下拉选、功能预设参数说明 */
        // 预设置输入参数
      this.functionTypeOptions
        // 筛选被选中的功能类型对象
        .filter(ft => ft.value === type)
        .map(ft => {
          console.log('选中的功能类型', JSON.stringify(ft))

          if(scope.model.inputParams && scope.model.inputParams.length>0) {
            let presetParamTypes = ft.params.map(presetParam => presetParam.metadata.type)
            scope.model.inputParams.forEach(inputParam => {
              if(presetParamTypes.includes(inputParam.type)) {
                inputParam = Object.assign(inputParam, { presetParam: ft.params.find(presetParam => presetParam.metadata.type === inputParam.type), disDelete: true })
                console.log('预设参数', JSON.stringify(inputParam))
              } else {
                inputParam = Object.assign(inputParam, { presetParam: {name: '请选择输入参数', description: '', type:""}, disDelete: false })
                console.log('非预设参数', JSON.stringify(inputParam))
              }
            })
          } else {
            // 如果model对对象没有输入参数信息
            ft.params.map(presetParam => scope.model.inputParams.push({ presetParam: presetParam, disDelete: true }))
          }
        })
      scope.$forceUpdate()
    },
    inputParamsDropdownVisible(open, presetParam) {
      console.log(presetParam)
      if (open) {
        let type = presetParam.metadata ? presetParam.metadata.type : ''
        this.getInputParamsOptions(type)
      }
    },
    getParamInputMode() {
      let scope = this
      getAction(this.url.getInputModes).then(res => {
        if (res.success) {
          scope.paramInputModeOptions = res.result
        }
      })
    },
    getFunctionTypes() {
      let scope = this
      getAction(this.url.getTypes).then(res => {
        if (res.success) {
          scope.functionTypeOptions = res.result
        }
      })
    },
    getExecutionWays() {
      let scope = this
      getAction(this.url.getExecutionWays).then(res => {
        if (res.success) {
          scope.executionWayOptions = res.result
        }
      })
    },
    validateDuplicateCode(modelId, funcId = '', funcCode = '', callback) {
      getAction(this.url.validateCode, { deviceModelId: modelId, funcId: funcId, funcCode: funcCode }).then(res => {
        res['success'] ? callback() : callback(res['message'])
      })
    },
    validateDuplicateName(modelId, funcId = '', funcName = '', callback) {
      getAction(this.url.validateName, { deviceModelId: modelId, funcId: funcId, funcName: funcName }).then(res => {
        res['success'] ? callback() : callback(res['message'])
      })
    },
    addRowParam() {
      const len = this.model.inputParams.length
      this.model.inputParams.push({ presetParam: { name: '请选择输入参数', description: '', type:"" }, disDelete: false, sort: len })
      this.$forceUpdate()
    },
    delRowParam(index) {
      console.log(index)
      this.model.inputParams.splice(index, 1)
      this.$forceUpdate()
    },
    close() {
      let scope = this
      this.$emit('close')
      this.form.resetFields();
      this.$nextTick(() => {
        scope.model = { }
        scope.$forceUpdate()
      })
      this.confirmLoading = false
      this.visible = false
    },
    add(modelId) {
      this.getInputParamsOptions()
      this.form.resetFields()
      this.model = JSON.parse(JSON.stringify(this.baseModel))
      this.model.modelId = modelId
      this.visible = true
    },
    edit(record) {
      let scope = this
      this.visible = true
      this.form.resetFields()
      this.model = JSON.parse(JSON.stringify(this.baseModel))
      this.model = Object.assign(this.model, record)
      // 提前写入预设参数，方式页面加载时报错
      this.model.inputParams.map((inputParam, index) => {
        Object.assign(inputParam, {presetParam: { name: "", description: "", type:""}, sort: !inputParam.sort?index:inputParam.sort, disDelete: true})
      })

      this.$nextTick(() => {
        scope.form.setFieldsValue(pick(scope.model, 'id', 'modelId', 'name', 'code', 'type', 'isSync', 'inputParams'))
        scope.$forceUpdate()
      })
    },
    handleOk() {
      const that = this
      // 触发表单验证
      this.$refs.functionForm.validate(valid => {
        if (valid) {
          that.confirmLoading = true
          let httpurl = ''
          let method = ''
          if (!this.model.id) {
            httpurl += this.url.add
            method = 'post'
          } else {
            httpurl += this.url.edit
            method = 'put'
          }
          let formData = JSON.parse(JSON.stringify(this.model))
          // 去除presetParam
          formData.inputParams.map(inputParam => {
            delete inputParam.presetParam
            delete inputParam.metadata
          });
          console.log('表单提交数据', formData)
          httpAction(httpurl, formData, method)
            .then(res => {
              console.log(res)
              if (res.success) {
                that.$message.success(res.message)
                that.$emit('ok')
              } else {
                that.$message.warning(res.message)
              }
            })
            .finally(() => {
              that.confirmLoading = false
              that.close()
            })
        }
      })
    },
    /**
     *
     * @param type
     * @returns {Promise}
     */
    getInputParamsOptions(type) {
      let that = this
      return new Promise((resolve, reject) => {
        getAction('/device/model/getWritableDeviceProperties', { deviceModelId: this.deviceModelId, type: type }).then(res => {
          if (res.success) {
            that.inputParamsOptions = JSON.parse(JSON.stringify(res.result))
            console.log(that.inputParamsOptions)
            resolve(res.result)
          }
        })
      })
    },
    getOutDataOptions() {
      let that = this
      getAction('/sys/dict/getDictItems/iot_device_data,name,id,rw_author!=\'w\' and device_model_by=' + this.deviceModelId, null).then(res => {
        console.log(res)
        if (res.success) {
          that.outDataOptions = res.result
        }
      })
    }
  }
}
</script>

<style lang="less" scoped></style>
